<?php
/**
 * location report model
 *
 * @author raphael seebacher <raphasee@ee.ethz.ch>
 * @version 0.1
 */
class location_report extends db_model {
    protected $data = Array(
      'user_id' => NULL,
      'latitude' => NULL,
      'longitude' => NULL,
      'accuracy' => NULL,
      'timestamp' => NULL,
      'provider' => NULL,
    );

    public function set($key, $value) {
        if (array_key_exists($key, $this->data)) {
            if (($key == 'provider')
                     && ($value != 'network')
                     && ($value !='gps')
            ) {
                throw new model_exception('Provider does not match.');
            }
            else if (($key == 'latitude')
                     && (
                       ($value > 90)
                       || ($value <-90)
                     )
            ) {
                throw new model_exception('Latitude out of bounds.');
            }
            else if (($key == 'longitude')
                     && (($value > 180) || ($value <-180))
            ) {
                throw new model_exception('Longitude out of bounds.');
            }

            $this->data[$key] = $value;
            return true;
        }
        else {
            throw new model_exception('Key not valid for model');
        }
    }

    public function save() {
        foreach ($this->data as $key => $value) {
            if ($value === NULL) {
                throw new model_exception(
                  'Saving not possible. Not all data given.'
                );
            }
        }

        $this->escape_data();

        $timestamp = date('Y-m-d H:i:s', $this->data['timestamp']);

        $q = 'INSERT IGNORE INTO user_location_report '
            .'(user_id, latitude, longitude, accuracy, timestamp, provider) '
            .'VALUES ('
            .$this->data['user_id'].','
            .$this->data['latitude'].','
            .$this->data['longitude'].','
            .$this->data['accuracy'].','
            .'\''.$timestamp.'\','
            .'\''.$this->data['provider'].'\') ';

        if (!self::$dbc->query_assoc($q)) {
            throw new model_exception('Saving not possible.');
        }
    }

    public static function get_user_location_reports($user_id) {
        $q = 'SELECT * FROM user_location_report WHERE user_id='
            .(self::$dbc->escape($user_id)).' ORDER BY timestamp DESC';
        $lrs_raw = self::$dbc->query_assoc($q);

        $result = Array();
        foreach ($lrs_raw as $lr_raw) {
            $result[] = new location_report($lr_raw);
        }

        return $result;
    }

    public static function get_newest_location_report($user_id) {
        $q = 'SELECT * FROM user_location_report WHERE user_id='
            .(self::$dbc->escape($user_id)).' ORDER BY timestamp DESC LIMIT 1';
        $lr_raw = self::$dbc->query_assoc($q);

        if (!is_array($lr_raw) || !count($lr_raw)) {
            throw new model_exception('No location report found for user!');
        }

        return new location_report($lr_raw[0]);
    }

    public function get_location_report_nearby($radius) {
        $result = Array();

        $q = 'SELECT user_id, latitude, longitude, '
            .'accuracy, timestamp, provider, '
            .'('
            .'6371000*ACOS('
            .'COS(RADIANS('.$this->data['latitude'].'))*COS(RADIANS(latitude))'
            .'*COS(RADIANS(longitude)'
            .'-RADIANS('.$this->data['longitude'].'))'
            .'+SIN(RADIANS('.$this->data['latitude'].'))'
            .'*SIN(RADIANS(latitude)))'
            .') AS distance '
            .'FROM '
            .'(SELECT * FROM user_location_report ORDER BY timestamp DESC) '
            .'AS user_location_report_ordered '
            .'WHERE user_id!=\''.$this->data['user_id'].'\' '
            .'GROUP BY user_id '
            .'HAVING distance<='.intval($radius).' '
            .'ORDER BY distance ASC';

        $lrs_raw = self::$dbc->query_assoc($q);

        foreach ($lrs_raw as $lr_raw) {
            $result[] = new location_report($lr_raw);
        }

        return $result;
    }

    public function distance($lr) {
        $latitude = $lr->get('latitude');
        $longitude = $lr->get('longitude');

        return 6371000*acos(
          cos(deg2rad($this->data['latitude']))
          *cos(deg2rad($latitude))
          *cos(deg2rad($longitude)-deg2rad($this->data['longitude']))
          +sin(deg2rad($this->data['latitude']))*sin(deg2rad($latitude))
        );
    }
}
?>